#ifndef MAINAPP_H
#define MAINAPP_H

#include <QMainWindow>
#include "SimulationManager.h"

/// @namespace Ui the Ui namespace created from the MainWindow class
namespace Ui
{
    class MainWindow;
}

/// @file MainApp.h
/// @brief represents the main gui application window, modified from JMacey's demo
/// @author Perseedoss Rajiv
/// @version 1.0
/// @date 12.04.11
/// Revision History :
/// Initial Version 12.04.11
/// @class MainApp
/// @brief contains all the UI extended from MainWindow.ui and our GLWindow

class MainApp : public QMainWindow
{
Q_OBJECT

public:
    /// @brief ctor
    /// @param[in] _parent the main application window for the GUI
    MainApp(
            QWidget* _parent = 0
            );

    /// @brief dtor
    ~MainApp();


private:
    /// @brief the handle to the main GUI window, used for creating all the UI and the gl window
    Ui::MainWindow* m_ui;

    /// @brief the main gl context that is used for drawing and creation of the cloth simulation
    SimulationManager* m_simulationManager;

private:
    /// @brief reinitialise simulation with batch parameters
    /// @param [in] _scenario the scenario to be reinitialised with
    void reInitialiseSimulation(const ConstrainedScenario _scenario);

    /// @brief convert a value from the simulation to that on the slider, given the range
    /// @param [in] _lowerTrue the lower value from the simulation
    /// @param [in] _lowerSlider the lower value of the slider
    /// @param [in] _lowerX the value from the simulation to convert
    int toSliderValue
            (
                const float _lowerTrue,
                const int _lowerSlider,
                const float _lowerX
            );

    /// @brief convert a value on the slider to the simulation, given the range
    /// @param [in] _lowerTrue the lower value from the simulation
    /// @param [in] _lowerSlider the lower value of the slider
    /// @param [in] _lowerX the value from the slider to convert
    float fromSliderValue
            (
                const float _lowerTrue,
                const int _lowerSlider,
                const int _lowerX
            );


    /// @brief setup up the UI intial values and connects signals/slots
    void setupConnections();

    /// @brief override the keyPressEvent inherited from QObject so we can handle key presses.
    /// @param [in] _event the event to process
    void keyPressEvent(
                       QKeyEvent* _event
                      );


private slots:
    /// @brief toggle automove for cloth simulation
    void on_cmd_autoMove_clicked();

    /// @brief single step through cloth simulation
    void on_cmd_singleStep_clicked();

    /// @brief activate solid curtain scenario
    void on_cmd_sim_solidCurtain_clicked();

    /// @brief activate banner scenario
    void on_cmd_sim_banner_clicked();

    /// @brief activate flag scenario
    void on_cmd_sim_flag_clicked();

    /// @brief activate shelter scenario
    void on_cmd_sim_shelter_clicked();

    /// @brief activate curtain scenario
    void on_cmd_sim_curtain_clicked();

    /// @brief activate tablecloth scenario
    void on_cmd_sim_tablecloth_clicked();

    /// @brief change view to front view
    void on_cmd_2DFrontView_clicked();

    /// @brief change view to top view
    void on_cmd_2DTopView_clicked();

    /// @brief unpin a column
    void on_cmd_internal_unpinColumn_clicked();

    /// @brief pin a column
    void on_cmd_internal_pinColumn_clicked();

    /// @brief unpin a row
    void on_cmd_internal_unpinRow_clicked();

    /// @brief pin a row
    void on_cmd_internal_pinRow_clicked();

    /// @brief unpin all particles
    void on_cmd_internal_unpinAll_clicked();

    /// @brief pin all particles
    void on_cmd_internal_pinAll_clicked();

    /// @brief toggle pin of trace particle
    /// @param [in] _checked toggle value
    void on_chk_internal_pinned_clicked(const bool _checked);

    /// @brief toggle internal trace on neighbours springs
    /// @param [in] _checked toggle value
    void on_chk_internal_traceNeighbours_clicked(const bool _checked);

    /// @brief change internal trace particle number
    /// @param [in] _value new trace particle index
    void on_spin_internal_particle_no_valueChanged(const int _value);

    /// @brief toggle internal trace
    /// @param [in] _checked toggle value
    void on_group_trace_clicked(const bool _checked);

    /// @brief change z position for cube obstacle
    /// @param [in] _value new z position
    void on_spin_cube_position_z_valueChanged(const int _value);

    /// @brief change y position for cube obstacle
    /// @param [in] _value new y position
    void on_spin_cube_position_y_valueChanged(const int _value);

    /// @brief change x position for cube obstacle
    /// @param [in] _value new x position
    void on_spin_cube_position_x_valueChanged(const int _value);

    /// @brief change z size for cube obstacle
    /// @param [in] _value new z size
    void on_spin_cube_size_z_valueChanged(const int _value);

    /// @brief change y size for cube obstacle
    /// @param [in] _value new y size
    void on_spin_cube_size_y_valueChanged(const int _value);

    /// @brief change x size for cube obstacle
    /// @param [in] _value new x size
    void on_spin_cube_size_x_valueChanged(const int _value);

    /// @brief change z position for sphere obstacle
    /// @param [in] _value new z position
    void on_spin_sphere_position_z_valueChanged(const int _value);

    /// @brief change y position for sphere obstacle
    /// @param [in] _value new y position
    void on_spin_sphere_position_y_valueChanged(const int _value);

    /// @brief change x position for sphere obstacle
    /// @param [in] _value new x position
    void on_spin_sphere_position_x_valueChanged(const int _value);

    /// @brief change sphere radius
    /// @param [in] _value new radius
    void on_spin_sphere_radius_valueChanged(const int _value);

    /// @brief toggle bbox drawing of cube obstacle
    /// @param [in] _checked toggle value
    void on_chk_cube_bbox_clicked(const bool _checked);

    /// @brief toggle sphere obstacle
    /// @param [in] _checked toggle value
    void on_group_sphere_clicked(const bool _checked);

    /// @brief toggle cube obstacle
    /// @param [in] _checked toggle value
    void on_group_cube_clicked(const bool _checked);

    /// @brief toggle obstacle
    /// @param [in] _checked toggle value
    void on_group_obstacle_clicked(const bool _checked);

    /// @brief change wind z direction
    /// @param [in] _value new z direction
    void on_spin_wind_direction_z_valueChanged(const int _value);

    /// @brief change wind y direction
    /// @param [in] _value new y direction
    void on_spin_wind_direction_y_valueChanged(const int _value);

    /// @brief change wind x direction
    /// @param [in] _value new x direction
    void on_spin_wind_direction_x_valueChanged(const int _value);

    /// @brief change wind strength
    /// @param [in] _value new strength
    void on_sld_wind_strength_valueChanged(const int _value);

    /// @brief toggle bend springs
    /// @param [in] _checked toggle value
    void on_chk_spring_bend_clicked(const bool _checked);

    /// @brief toggle stretch springs
    /// @param [in] _checked toggle value
    void on_chk_spring_stretch_clicked(const bool _checked);

    /// @brief toggle structural springs
    /// @param [in] _checked toggle value
    void on_chk_spring_structural_clicked(const bool _checked);

    /// @brief toggle wind
    /// @param [in] _checked toggle value
    void on_group_wind_clicked(const bool _checked);

    /// @brief toggle gravity
    /// @param [in] _checked toggle value
    void on_chk_force_gravity_clicked(const bool _checked);

    /// @brief change damping coefficient
    /// @param [in] _value new damping
    void on_sld_cloth_dampiness_valueChanged(const int _value);

    /// @brief change stiffness
    /// @param [in] _value new stiffness
    void on_sld_cloth_stiffness_valueChanged(const int _value);

    /// @brief change material
    /// @param [in] _value new material index
    void on_cmb_cloth_material_currentIndexChanged(const int _value);

    /// @brief toggle drawing mode
    /// @param [in] _checked toggle flag for wireframe
    void on_chk_cloth_wireframe_clicked(const bool _checked);

    /// @brief reinitialise simulation with a scenario
    void on_cmd_reInitialiseSimulation_clicked();

};

#endif // MAINAPP_H
